//
// 有 n 个城市，其中一些彼此相连，另一些没有相连。如果城市 a 与城市 b 直接相连，且城市 b 与城市 c 直接相连，那么城市 a 与城市 c 间接相连
//。 
// 
//
// 省份 是一组直接或间接相连的城市，组内不含其他没有相连的城市。 
//
// 给你一个 n x n 的矩阵 isConnected ，其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连，而 
//isConnected[i][j] = 0 表示二者不直接相连。 
//
// 返回矩阵中 省份 的数量。 
//
// 
//
// 示例 1： 
// 
// 
//输入：isConnected = [[1,1,0],[1,1,0],[0,0,1]]
//输出：2
// 
//
// 示例 2： 
// 
// 
//输入：isConnected = [[1,0,0],[0,1,0],[0,0,1]]
//输出：3
// 
//
// 
//
// 提示： 
//
// 
// 1 <= n <= 200 
// n == isConnected.length 
// n == isConnected[i].length 
// isConnected[i][j] 为 1 或 0 
// isConnected[i][i] == 1 
// isConnected[i][j] == isConnected[j][i] 
// 
//
// 
//
// 
// 注意：本题与主站 547 题相同： https://leetcode-cn.com/problems/number-of-provinces/ 
//
// Related Topics 深度优先搜索 广度优先搜索 并查集 图 👍 66 👎 0


package LeetCode.editor.cn;


import java.util.Deque;
import java.util.LinkedList;

/**
 * @author ldltd
 * @date 2025-04-15 10:12:34
 * @description LCR 116.省份数量
 
 */
 
public class BLyHh0 {
    public static void main(String[] args) {
    //测试代码
    BLyHh0 fun = new BLyHh0();
    Solution solution= fun.new Solution();
    
    }

//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    boolean [] vis;
    public int findCircleNum1(int[][] isConnected) {
        vis=new boolean[isConnected.length];
        int res=0;
        for (int i = 0; i < isConnected.length; i++) {
            if(!vis[i]){
                vis[i]=true;
                res++;
                dfs(isConnected,i);
            }
        }
        return res;
    }
    private void dfs(int[][] ar,int i){
        for (int j = 0; j < ar.length; j++) {
            if(ar[i][j]==1&&!vis[j]) {
                vis[j]=true;
                dfs(ar,j);
            }
        }
    }
    //bfs
    public int findCircleNum2(int[][] isConnected) {
        vis=new boolean[isConnected.length];
        Deque<Integer> q=new LinkedList<>();
        int res=0;
        for (int i = 0; i < isConnected.length; i++) {
            if(!vis[i]) {
                q.offer(i);
                res++;
                while (!q.isEmpty()){
                    Integer poll = q.poll();
                    vis[poll]=true;
                    for (int j = 0; j < isConnected.length; j++) {
                        if(!vis[j]&&isConnected[poll][j]==1){
                            q.offer(j);
                        }
                    }
                }
            }
        }
        return res;
    }

    //并查集
    public int findCircleNum(int[][] isConnected){
        int []p=new int[isConnected.length];
        //首先每个城市自己是一个集合
        for (int i = 0; i < isConnected.length; i++) {
            p[i]=i;
        }

        for (int i = 0; i < isConnected.length; i++) {
            for (int j = i+1; j < isConnected.length; j++) {
                //如果两个城市联通，把j插入i，即合并
                if(isConnected[i][j]==1){
                    //即j的父节点就会赋为i的父节点
                    p[find(j,p)]=find(i,p);
                }
            }
        }
        int res=0;
        for (int i = 0; i < isConnected.length; i++) {
            //最后查看有几个城市的父节点没有改变就有几个集合
            if(p[i]==i){
                res++;
            }
        }
        return res;
    }
    private int find(int x,int[] p){
        //如果他的父节点不是自己，那么找到他的父节点，然后赋值，最后返回父节点
        if(p[x]!=x) p[x]=find(p[x],p);
        return p[x];
    }
}
//leetcode submit region end(Prohibit modification and deletion)

}
